import datetime
import os
import re
from copy import deepcopy
from typing import *

import pandas as pd
from utils.error import PreparationError
from utils.strategy.loader import StrategyLoader

kline_map = {
    'minute': 60,
    'hour': 60 * 60,
    'day': 60 * 60 * 24,
}


class BaseConf:

    def __init__(self, strategy_name: str, s_time: str, e_time: str, show_factors: List[str] = None, **kwargs):
        try:
            s_group = re.match(r'^(\d{4})[-\\/](\d{1,2})[-\\/](\d{1,2})(\s(\d\d):(\d\d):(\d\d))?$', s_time).groups()
            e_group = re.match(r'^(\d{4})[-\\/](\d{1,2})[-\\/](\d{1,2})(\s(\d\d):(\d\d):(\d\d))?$', e_time).groups()
        except AttributeError:
            raise PreparationError(f'错误的时间格式')
        if s_group[3] is None:
            self.s_time = datetime.datetime(int(s_group[0]), int(s_group[1]), int(s_group[2]),
                                            tzinfo=datetime.timezone.utc)
        else:
            self.s_time = datetime.datetime(int(s_group[0]), int(s_group[1]), int(s_group[2]), int(s_group[4]),
                                            int(s_group[5]), int(s_group[6]), tzinfo=datetime.timezone.utc)
        if e_group[3] is None:
            self.e_time = datetime.datetime(int(e_group[0]), int(e_group[1]), int(e_group[2]),
                                            tzinfo=datetime.timezone.utc)
        else:
            self.e_time = datetime.datetime(int(e_group[0]), int(e_group[1]), int(e_group[2]), int(e_group[4]),
                                            int(e_group[5]), int(e_group[6]), tzinfo=datetime.timezone.utc)
        self.strategy_name = strategy_name
        self.strategy: StrategyLoader = StrategyLoader(strategy_name)
        self.strategy.system_conf.update(kwargs)
        # 序列化时暂存策略设置项
        self._attr = None
        # 需要展示的因子值
        self.show_factors: List[str] = show_factors


    def reload(self):
        """
        从文件重加载策略并保持设置不变
        :return:
        """
        self._attr = self.strategy.system_conf.copy()
        self.strategy = StrategyLoader(self.strategy_name)
        self.strategy.system_conf.update(self._attr)
        self._attr = None

    @property
    def period(self):
        return kline_map[self.strategy.Kline]

    def load_data(self) -> pd.DataFrame:
        pass

    def __getstate__(self):
        self._attr = self.strategy.system_conf.copy()
        state = self.__dict__.copy()
        del state['strategy']
        return state

    def __setstate__(self, state):
        self.__dict__.update(state)
        self.strategy = StrategyLoader(self.strategy_name)
        self.strategy.system_conf.update(self._attr)

    def copy(self, **kwargs) -> 'BaseConf':
        """
        复制配置并修改参数
        :param kwargs:
        :return:
        """
        new = deepcopy(self)
        new.strategy.system_conf.update(kwargs)
        return new

    def __setitem__(self, key: str, value: Any):
        self.strategy.system_conf[key] = value

    def __getitem__(self, key: str) -> Any:
        return self.strategy.system_conf[key]


